package com.zlyx.easy.dev.remote;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zlyx.easy.core.list.Lists;
import com.zlyx.easy.core.map.ObjectMap;
import com.zlyx.easy.core.tool.Ops;
import com.zlyx.easy.core.utils.LogUtils;
import com.zlyx.easy.core.utils.RestUtils;
import com.zlyx.easy.core.utils.SpringUtils;
import com.zlyx.easy.core.utils.TypeUtils;
import com.zlyx.easy.dev.DevException;

public class RemoteUtils {

	public static Object doProcess(String host, Method method, Object[] args) {
		try {
			Map<String, Object> resultData = RestUtils.postForObject(host + "remote/method/call",
					ObjectMap.newMap("method", method).addValue("args", args).toString());
			if (resultData != null) {
				if (0 == (int) resultData.get("code")) {
					if (TypeUtils.isBaseType(TypeUtils.typeNameFor(method.getReturnType()))) {
						return resultData.get("data");
					} else if (Ops.isNotNull(resultData.get("data"))) {
						return JSON.parseObject(JSON.toJSONString(resultData.get("data")), method.getReturnType());
					}
				} else {
					DevException.throwException(resultData.get("message"));
				}
			}
		} catch (Throwable e) {
			LogUtils.err(e);
		}
		return null;
	}

	public static Object callMethod(JSONObject methodStr, Object[] args) throws Exception {
		Class<?> declaringClass = Class.forName(methodStr.getString("declaringClass"));
		Object target = SpringUtils.getBeanByType(declaringClass);
		Method method = target.getClass().getMethod(methodStr.getString("name"),
				parseParameterTypes(methodStr.getJSONArray("parameterTypes")));
		return method.invoke(target, args);
	}

	public static Class<?>[] parseParameterTypes(JSONArray parameterTypeNames) throws Exception {
		List<Class<?>> parameterTypes = Lists.newList();
		for (Object parameterTypeName : parameterTypeNames) {
			if (TypeUtils.isBaseType((String) parameterTypeName)) {
				parameterTypes.add(TypeUtils.getBaseType(parameterTypeName));
			} else {
				parameterTypes.add(Class.forName((String) parameterTypeName));
			}
		}
		return parameterTypes.toArray(new Class<?>[parameterTypeNames.size()]);
	}
}
